package com.squirrel.common.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.squirrel.common.entity.User;
import com.squirrel.common.entity.UserSubscription;
import com.squirrel.common.mapper.*;
import com.squirrel.common.param.user.*;
import com.squirrel.common.param.video.PageParam;
import com.squirrel.common.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.squirrel.common.util.*;
import com.squirrel.common.vo.LoginVO;
import com.squirrel.common.exception.BaseException;
import com.squirrel.common.response.code.CodeEnum;
import com.squirrel.common.vo.user.UserInfoVO;
import com.squirrel.common.vo.video.VideoUpVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * <p>
 * UserServiceImp 用户服务实现类
 * </p>
 *
 * @author 关远键
 * @since 2021/11/10 14:25
 */
@Service
@Slf4j
@Transactional
public class UserServiceImp extends ServiceImpl<UserMapper, User> implements UserService {

    @Value("${file.coming.path}")
    private String url;

    @Value("${file.upload.path}")
    private String path;

    @Autowired
    UserMapper userMapper;
    
    @Autowired
    RedisUtil redisUtil;
    
    @Autowired
    MailServiceImpl mailService;
    
    @Autowired
    private UserSubscriptionMapper usMapper;

    @Autowired
    private UserVideoMapper uvMapper;

    @Autowired
    private UserCommentMapper ucMapper;

    @Autowired
    private VideoMapper videoMapper;

    /**
     * 登录
     *
     * @param loginParam
     * @return com.squirrel.common.vo.user.LoginVO
     * @author 关远键
     * @date 2021/11/10 15:21
     */
    @Override
    public LoginVO login(HttpServletResponse response, LoginParam loginParam) {
        String mailOrPhone = loginParam.getMailOrPhone();
        User user = userMapper.getUserByMailOrPhone(mailOrPhone);

        // 用户不存在
        if (null == user) {
            throw new BaseException(CodeEnum.NOT_EXISTS);
        }

        if (!mailOrPhone.contains("@") && user.getPassword().equals("null")) {
            throw new BaseException(CodeEnum.NON_PASSWORD);
        }

//        String password = PasswordUtils.encode(loginParam.getMail(), loginParam.getPassword());
        String password = loginParam.getPassword();

        // 密码错误
        if (!user.getPassword().equals(password)) {
            throw new BaseException(CodeEnum.LOGIN_FAIL);
        }

        return createToken(response, user);

    }

    /**
     * 通过邮箱登录
     *
     * @param response user
     * @return com.squirrel.common.vo.LoginVO
     * @author 林煜岚
     * @date 2021/11/15 12:33
     */
    @Override
    public LoginVO loginByMail(HttpServletResponse response, LoginByMailParam loginByMailParam) {
        User user = userMapper.getUserByMailOrPhone(loginByMailParam.getMail());
        // 用户不存在
        if (null == user) {
            throw new BaseException(CodeEnum.NOT_EXISTS);
        }

        redisUtil.get(loginByMailParam.getMail());
        // 验证码错误错误
        if (redisUtil.hasKey(loginByMailParam.getMail()) &&
                redisUtil.get(loginByMailParam.getMail())
                        .equals(loginByMailParam.getAuthCode())) {
            return createToken(response, user);
        } else {
            throw new BaseException(CodeEnum.LOGIN_MAIL_FAIL);
        }


    }

    /**
     * 注册
     *
     * @param registerParam
     * @return Boolean
     * @author 林煜岚
     * @date 2021/11/15 12:33
     */
    @Override
    public Boolean register(RegisterParam registerParam) {
        Integer byMail = userMapper.getByMail(registerParam.getMail());
        Integer byNickname = userMapper.getByNickname(registerParam.getNickname());

        if (0 != byMail || 0 != byNickname) {
            log.info("邮箱已注册或用户名已存在");
            throw new BaseException(CodeEnum.REGISTER_EXISTS);
        } else {

            log.info(redisUtil.get(registerParam.getMail()).toString());
            // 邮箱验证
//            mailService
            if (redisUtil.get(registerParam.getMail()).equals(registerParam.getAuthCode())) {
                String mail = registerParam.getMail();
                String password = registerParam.getPassword();
//                String pwd = PasswordUtils.encode(mail, password);
                userMapper.reg(registerParam.getNickname(), mail, password);
            } else {
                throw new BaseException(CodeEnum.PERMISSION_TOKEN_EXPIRED);
            }

        }

        return true;
    }

    /**
     * 获取邮箱验证码
     *
     * @param mail
     * @return com.squirrel.common.entity.User
     * @author 林煜岚
     * @date 2021/11/15 12:42
     */
    @Override
    public String createAuthCode(String mail) {
//        String result = "";
        //生成随机6位的验证码
        StringBuffer authCode = new StringBuffer();
        char[] codeSequence = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',

                'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',

                'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        int codeLen = codeSequence.length;
        int randCodeLen = 6;
        for (int i = 0; i < randCodeLen; i++) {
            Random random = new Random();
            int codeIndex = random.nextInt(codeLen);
            authCode.append(codeSequence[codeIndex]);
        }

        //发送验证码
        String mailSubject = "松鼠视频网";
        try {
            mailService.sendSimpleMail(mail, mailSubject, "验证码:" + authCode);
            redisUtil.set(mail, authCode, 30000);
            return "已发送";
//            result = "已发送";
        } catch (MailException mailException) {
            log.error(mailException.getMessage());
            throw new BaseException(CodeEnum.MAIL_NOT_EXISTS);
        }

//        return result;
    }

    /**
     * 根据邮箱号获取用户信息
     *
     * @param mail
     * @return com.squirrel.common.entity.User
     * @author 关远键
     * @date 2021/11/10 16:42
     */
    @Override
    public User getUserByMail(String mail) {
        return userMapper.getUserByMailOrPhone(mail);
    }

    /**
     * 查询用户信息，提供给其他接口使用
     * @author 关远键
     * @date 2021/11/22 10:17
     * @param userId 用户ID
     * @return com.squirrel.common.entity.User
     */
    @Override
    public User getUserById(Integer userId) {
        return userMapper.selectById(userId);
    }

    /**
     * 关键字搜索用户ID
     * @author 关远键
     * @date 2021/11/28 19:19
     * @param pageParam 分页
     * @param nickname 用户昵称
     * @return java.util.List<java.lang.Integer>
     */
    @Override
    public List<Integer> getUserIdByKey(PageParam pageParam, String nickname) {
        Page<Integer> page = new Page<>();
        IPage<Integer> userIdByKey = userMapper.getUserIdByKey(page, nickname);

        if (0 == userIdByKey.getTotal()) {
            return null;
        }

        return new ArrayList<>(userIdByKey.getRecords());
    }

    /**
     * 修改用户信息
     *
     * @param param 修改参数
     * @return boolean
     * @author 关远键
     * @date 2021/11/22 15:16
     */
    @Override
    public String modify(MultipartFile avatar, ModifyParam param) {
        User user = userMapper.selectById(param.getUserId());

        if (null == user) {
            throw new BaseException(CodeEnum.NOT_EXISTS);
        }

        String avatarFileName = ImageToolUtils.saveAvatar(param.getNickname(), avatar, path);

        user.setAvatar(avatarFileName);
        user.setNickname(param.getNickname());
        user.setIntro(param.getIntro());

        if (0 < userMapper.updateById(user)) {
            return avatarFileName;
        }

        throw new BaseException(CodeEnum.DB_EXCEPTION);
    }

    /**
     * 获取作者信息
     * @author 关远键
     * @date 2021/11/23 14:26
     * @param id 作者ID
     * @return com.squirrel.common.vo.user.UserInfoVO
     */
    @Override
    public UserInfoVO getAuthorInfo(Integer id) {
        UserInfoVO authorInfo = userMapper.getAuthorInfo(id);
        if (null != authorInfo) {
            Integer userId = authorInfo.getUserId();

            authorInfo.setAvatar(url + authorInfo.getAvatar());
            authorInfo.setIdol(usMapper.countByFromUserId(userId));
            authorInfo.setFans(usMapper.countByToUserId(userId));
            authorInfo.setCollect(uvMapper.collectByUserId(userId));

            List<VideoUpVO> works = videoMapper.getByAuthor(id);
            int good = ucMapper.countGoodByUserId(userId);
            if ( 0 != works.size()) {
                for (VideoUpVO work: works) {
                    good += uvMapper.likeByVideoId(work.getId());
                    work.setImage(url + work.getImage());
                }
            }

            authorInfo.setGood(good);
            authorInfo.setList(works);

            return authorInfo;
        }

        throw new BaseException(CodeEnum.NOT_EXISTS);
    }

    /**
     * 短信验证登录
     * @author 关远键
     * @date 2021/11/24 11:02
     * @param param 手机登录参数
     * @return boolean
     */
    @Override
    public LoginVO loginByPhone(HttpServletResponse response, PhoneLoginParam param) {
        String phone = param.getPhone();
        Integer verificationCode = param.getVerificationCode();

        if (!redisUtil.hasKey(phone)) {
            if (verificationCode == redisUtil.get(phone)) {
                User user = userMapper.getUserByMailOrPhone(phone);
                // 用户不存在
                if (null == user) {
                    throw new BaseException(CodeEnum.NOT_EXISTS);
                }

                return createToken(response, user);
            }
        }

        throw new BaseException(CodeEnum.NOT_EXISTS);
    }

    /**
     * 发送手机短信，首次注册
     * @author 关远键
     * @date 2021/11/24 10:42
     * @param param 手机号
     * @return boolean 是否成功注册
     */
    @Override
    public boolean getCodeByPhone(PhoneParam param) {
        String phone = param.getPhone();

        Integer verificationCode = LoginByPhoneUtils.sendAndGet(phone);
        redisUtil.set(phone, verificationCode, 1000 * 60 * 5);  // 5分钟
        System.out.println("redis:【" + phone + "】=====>" + redisUtil.get(phone));

        // 注册到数据库
        if (null == userMapper.getUserByMailOrPhone(phone)) {
            return 0 < userMapper.reg(phone, phone, "null");
        } else {
            return true;
        }


    }


    /**
     * 根据用户信息生成token
     *
     * @param response user
     * @return com.squirrel.common.vo.LoginVO
     * @author 林煜岚
     * @date 2021/11/15 12:33
     */
    private LoginVO createToken(HttpServletResponse response, User user) {
        //JWT 方式生成的 token
        Audience audience = Audience.getInstance();
        String token = JwtTokenUtil.createJWT(String.valueOf(user.getId()), user.getNickname(), audience);
        response.setHeader(JwtTokenUtil.AUTH_HEADER_KEY, token);

        return LoginVO.builder()
                .userId(user.getId())
                .name(user.getNickname())
                .avatar(url + user.getAvatar())
                .token(token)
                .build();
    }
}
